package com.ly.anno.junit;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;


public class JunitRunner {

    public static void main(String[] args) throws Exception {
        JunitRunner runner = new JunitRunner();
        runner.runTest(MathBizTest.class);
    }

    public void runTest(Class testClass) throws Exception {
        // 创建测试对象
        // 相当于 new XXX()
        Object tester = testClass.newInstance();

        List<Method> befores = new ArrayList<>();
        List<Method> afters = new ArrayList<>();
        List<Method> tests = new ArrayList<>();

        Method[] methods = testClass.getDeclaredMethods();

        for (Method method : methods) {
            if(method.getAnnotation(Before.class)!=null){
                befores.add(method);
            }
            if(method.getAnnotation(After.class)!=null){
                afters.add(method);
            }
            if(method.getAnnotation(Test.class)!=null){
                tests.add(method);
            }
        }

        // TODO 扩展: 对测试方法排序

        for (Method test : tests) {
            for (Method before : befores) {
                before.invoke(tester);
            }
            try{
                test.invoke(tester);
            } catch (InvocationTargetException e){
                // 获取异常原因
                Throwable cause = e.getCause();
                System.out.println(" 方法业务异常 " + cause);
            } catch (AssertException e) {
                System.out.println(" 测试结果错误 ");
            }
            // 测试方法执行到这里, 表示测试通过
            for (Method after : afters) {
                after.invoke(tester);
            }
        }

        // TODO 请统计 正确的测试结果数据量, 异常数量, 错误的数量

        System.out.println("测试结果");
    }

}

@Retention(RetentionPolicy.RUNTIME)
@interface Test {
    int value();
}

@Retention(RetentionPolicy.RUNTIME)
@interface Before {

}

@Retention(RetentionPolicy.RUNTIME)
@interface After {

}

class Assert {
    public static void assertEquals(Object aspect, Object act){
        if(!aspect.equals(act)){
            String s = String.format("期待结果是:%s, 实际记过是:%s", aspect, act);
            throw new AssertException(s);
        }
    }
}

class AssertException extends RuntimeException {
    public AssertException(String message) {
        super(message);
    }
}